﻿using System;
namespace AzukiMap.Tools.Logger
{
    public enum LogLevel
    {
        All = 0,
        Debug,
        Info,
        Warn,
        Error,
        Fatal,
    }

    /// <summary>
    /// Simple logger.
    /// This is workable when application is running on DEBUG mode.
    /// </summary>
    public static class Logger
    {
        static LogLevel _logLevel;
        const int _NUM_OF_SKIP_FRAME = 3;

        public static LogLevel LogLevel
        {
            get { return Logger._logLevel; }
            set { Logger._logLevel = value; }
        }

        public static void All(string message)
        {
            PrintLog(LogLevel.All, message);
        }

        public static void Debug(string message)
        {
            PrintLog(LogLevel.Debug, message);
        }

        public static void Info(string message)
        {
            PrintLog(LogLevel.Info, message);
        }

        public static void Warn(string message)
        {
            PrintLog(LogLevel.Warn, message);
        }

        public static void Error(string message)
        {
            PrintLog(LogLevel.Error, message);
        }

        public static void Fatal(string message)
        {
            PrintLog(LogLevel.Fatal, message);
        }

        public static void All(string message, Exception ex)
        {
            message += "\n" + ex.Message + "\n" + ex.StackTrace;
            All(message);
        }

        public static void Debug(string message, Exception ex)
        {
            message += "\n" + ex.Message + "\n" + ex.StackTrace;
            Debug(message);
        }
        
        public static void Info(string message, Exception ex)
        {
            message += "\n" + ex.Message + "\n" + ex.StackTrace;
            Info(message);
        }

        public static void Warn(string message, Exception ex)
        {
            message += "\n" + ex.Message + "\n" + ex.StackTrace;
            Warn(message);
        }

        public static void Error(string message, Exception ex)
        {
            message += "\n" + ex.Message + "\n" + ex.StackTrace;
            Error(message);
        }

        public static void Fatal(string message, Exception ex)
        {
            message += "\n" + ex.Message + "\n" + ex.StackTrace;
            Fatal(message);
        }

        static void PrintLog(LogLevel level, string logMessage)
        {
#if DEBUG
            if (_logLevel <= level)
            {
                string output;
                /*
                try
                {
                    FileAndLine fl = GetSourceFileAndLine(_NUM_OF_SKIP_FRAME);
                    output = _LINE_SEPARATOR + "\n" + "[" + level.ToString() + " "
                        + fl.FileName + ":" + fl.LineNum + "] " + logMessage;
                }
                catch (Exception e)
                {
                 */
                    DateTime now = DateTime.Now;
                    output = "[" + level.ToString() + " " + now.ToString() + "] " + logMessage;
                //}
                System.Diagnostics.Debug.WriteLine(output);
            }
#endif
        }

        // this cannot use on SL
        // only for nunit.
        static FileAndLine GetSourceFileAndLine(int skipFrame)
        {
            FileAndLine res = new FileAndLine();
            System.Diagnostics.StackFrame CallStack = new System.Diagnostics.StackFrame(skipFrame, true);

            string SourceFile = CallStack.GetFileName();
            int SourceLine = CallStack.GetFileLineNumber();

            res.FileName = SourceFile;
            res.LineNum = SourceLine;

            return res;
        }

        struct FileAndLine
        {
            public string FileName;
            public int LineNum;
        }
    }
}
